#pragma once
#include <iostream>
#include "Socket.hpp"
#include "Connection.hpp"
using namespace std;

class Acceptor
{
    using AcceptCallback = function<void(int)>;

public:
    // 不能将启动读事件监控，放到构造函数中，必须在设置回调函数后，再去启动
    // 否则有可能造成启动监控后，立即有事件，处理的时候，回调函数还没设置：新连接得不到处理，且资源泄漏
    Acceptor(EventLoop *loop, int port) : _socket(CreateServer(port)), _loop(loop),
                                          _channel(loop, _socket.Fd())
    {
        _channel.SetReadCallback(bind(&Acceptor::HandleRead, this));
    }
    void SetAcceptCallback(const AcceptCallback &cb) { _accept_callback = cb; }
    void Listen() { _channel.EnableRead(); }

private:
    // 监听套接字的读事件回调处理函数---获取新连接，调用_accept_callback函数进行新连接处理
    void HandleRead()
    {
        int newfd = _socket.Accept();
        if (newfd < 0)
        {
            return;
        }
        if (_accept_callback)
            _accept_callback(newfd);
    }
    int CreateServer(int port)
    {
        bool ret = _socket.CreateServer(port);
        assert(ret == true);
        return _socket.Fd();
    }

private:
    Socket _socket;   // 用于创建监听套接字
    EventLoop *_loop; // 用于对监听套接字进行事件监控
    Channel _channel; // 用于对监听套接字进行事件管理
    AcceptCallback _accept_callback;
};

class TcpServer
{
    using ConnectedCallback = function<void(const PtrConnection &)>;
    using MessageCallback = function<void(const PtrConnection &, Buffer *)>;
    using ClosedCallback = function<void(const PtrConnection &)>;
    using AnyEventCallback = function<void(const PtrConnection &)>;
    using Functor = function<void()>;

public:
    TcpServer(int port) : _port(port),
                          _next_id(0),
                          _enable_inactive_release(false),
                          _acceptor(&_baseloop, port),
                          _pool(&_baseloop)
    {
        _acceptor.SetAcceptCallback(bind(&TcpServer::NewConnection, this, placeholders::_1));
        _acceptor.Listen(); // 将监听套接字挂到baseloop上
    }
    void SetThreadCount(int count) { return _pool.SetThreadCount(count); }
    void SetConnectedCallback(const ConnectedCallback &cb) { _connected_callback = cb; }
    void SetMessageCallback(const MessageCallback &cb) { _message_callback = cb; }
    void SetClosedCallback(const ClosedCallback &cb) { _closed_callback = cb; }
    void SetAnyEventCallback(const AnyEventCallback &cb) { _event_callback = cb; }
    void EnableInactiveRelease(int timeout)
    {
        _timeout = timeout;
        _enable_inactive_release = true;
    }
    // 用于添加一个定时任务
    void RunAfter(const Functor &task, int delay)
    {
        _baseloop.RunInLoop(bind(&TcpServer::RunAfterInLoop, this, task, delay));
    }
    void Start()
    {
        _pool.Create();
        _baseloop.Start();
    }

private:
    void RunAfterInLoop(const Functor &task, int delay)
    {
        _next_id++;
        _baseloop.TimerAdd(_next_id, delay, task);
    }
    // 为新连接构造一个Connection进行管理
    void NewConnection(int fd)
    {
        _next_id++;
        PtrConnection conn(new Connection(_pool.NextLoop(), _next_id, fd));
        conn->SetMessageCallback(_message_callback);
        conn->SetClosedCallback(_closed_callback);
        conn->SetConnectedCallback(_connected_callback);
        conn->SetAnyEventCallback(_event_callback);
        conn->SetSrvClosedCallback(bind(&TcpServer::RemoveConnection, this, placeholders::_1));
        if (_enable_inactive_release)
            conn->EnableInactiveRelease(_timeout); // 启动非活跃超时销毁
        conn->Established();                       // 就绪初始化
        _conns.insert(make_pair(_next_id, conn));
    }
    void RemoveConnectionInLoop(const PtrConnection &conn)
    {
        int id = conn->Id();
        auto it = _conns.find(id);
        if (it != _conns.end())
        {
            _conns.erase(it);
        }
    }
    // 从管理Connection的_conns中移除连接信息
    void RemoveConnection(const PtrConnection &conn)
    {
        _baseloop.RunInLoop(bind(&TcpServer::RemoveConnectionInLoop, this, conn));
    }

private:
    uint64_t _next_id; // 这是一个自动增长的连接ID，
    int _port;
    int _timeout;                                  // 这是非活跃连接的统计时间---多长时间无通信就是非活跃连接
    bool _enable_inactive_release;                 // 是否启动了非活跃连接超时销毁的判断标志
    EventLoop _baseloop;                           // 这是主线程的EventLoop对象，负责监听事件的处理
    Acceptor _acceptor;                            // 这是监听套接字的管理对象
    LoopThreadPool _pool;                          // 这是从属EventLoop线程池
    unordered_map<uint64_t, PtrConnection> _conns; // 保存管理所有连接对应的shared_ptr对象
    ConnectedCallback _connected_callback;
    MessageCallback _message_callback;
    ClosedCallback _closed_callback;
    AnyEventCallback _event_callback;
};

class NetWork
{
public:
    NetWork()
    {
        lg(Info, "SIGPIPE INIT");
        signal(SIGPIPE, SIG_IGN);
    }
};
static NetWork nw;